﻿using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;
using System;
using System.Collections.Concurrent;
using IoTSignalR;
using System.Linq;
using System.Collections.Generic;
//只能处理一种协议，管道通信协议，现在是有状态管理，可以实现群发，广播，点对点
//socket 要和你通信，那个大哥说，我不支持管道通信，socket,mqtt,
//命名管道，匿名管道通信，在管道状态下，如何发送给socket连接的状态，如何发送给signale，http，tcp,longlooping
//策略模式和中介者模式结合实现
public class NamePipeServer
{
    private readonly string pipeName;
    private readonly PipeDirection direction;
    private readonly int maxNumberOfServerInstances;
    private readonly PipeTransmissionMode transmissionMode;
    private readonly PipeOptions options;

    public ConcurrentDictionary<string, NamedPipeServerStream> _clients = new ConcurrentDictionary<string, NamedPipeServerStream>();

    public event EventHandler<NotifyEventArg> SendMessageAfter;
    public event EventHandler<NotifyEventArg> ReceiveMessagesAfter;
    public event EventHandler<NotifyEventArg> OnConnected;
    public event EventHandler<NotifyEventArg> OnDisconnected;
    public event EventHandler<NotifyEventArg> OnReceiveErro;
    public event EventHandler<NotifyEventArg> OnSendErro;
    public event EventHandler<string> OnBusError;
    public NamePipeServer(string pipeName,
        PipeDirection direction,
        int maxNumberOfServerInstances,
        PipeTransmissionMode transmissionMode,
        PipeOptions options)
    {
        this.pipeName = pipeName;
        this.direction = direction;
        this.maxNumberOfServerInstances = maxNumberOfServerInstances;
        this.transmissionMode = transmissionMode;
        this.options = options;
    }

    public void Start()
    {
        Task.Run(async () =>await ListenInPipeServer());
        async Task ListenInPipeServer()
        {
            // 服务端
            while (true)
            {
                try
                {
                    var namedPipeServerStream = new NamedPipeServerStream(pipeName, direction, maxNumberOfServerInstances, transmissionMode, options);
                    await namedPipeServerStream.WaitForConnectionAsync();
                    var guid = Guid.NewGuid().ToString();
                    _clients[guid] = namedPipeServerStream;
                    OnConnected?.Invoke(this, new NotifyEventArg(guid, "客户端加入"));              
                    _ = Task.Run(async () =>await HandleClient(guid, namedPipeServerStream));
                }
                catch (Exception ex)
                {
                    OnBusError?.Invoke(this, ex.Message);
                }
            }
            async Task HandleClient(string clientId, NamedPipeServerStream namedPipeServerStream)
            {
                try
                {
                    while (namedPipeServerStream.IsConnected)
                    {
                        byte[] buffer = new byte[1024];
                        int bytesRead = await namedPipeServerStream.ReadAsync(buffer, 0, buffer.Length);
                        if (bytesRead > 0)
                        {
                            string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                            ReceiveMessagesAfter?.Invoke(this, new NotifyEventArg(clientId, message));
                        }
                    }
                }
                catch (Exception ex)
                {
                    OnReceiveErro?.Invoke(this, new NotifyEventArg(clientId, ex.Message));
                }
                finally
                {
                    this.OnDisconnected.Invoke(this, new NotifyEventArg(clientId, "客户端离开"));
                    _clients.TryRemove(clientId, out _);
                    namedPipeServerStream.Dispose();
                }
            }
        }
    }

    public async Task SendMessage(string clientId, string msg)
    {
        try
        {
            if (_clients.TryGetValue(clientId, out NamedPipeServerStream namedPipeServerStream))
            {
                if (namedPipeServerStream.IsConnected)
                {
                    byte[] bufferBack = Encoding.UTF8.GetBytes(msg);
                    await namedPipeServerStream.WriteAsync(bufferBack, 0, bufferBack.Length);
                    await namedPipeServerStream.FlushAsync();
                    SendMessageAfter?.Invoke(this, new NotifyEventArg(clientId, msg));
                    //消息记录，消息记数。。。。。。
                }
                else
                {
                    SendMessageAfter?.Invoke(this, new NotifyEventArg(clientId, "客户端未连接"));
                    //消息记录，消息记数。。。。。。
                }
            }
            else
            {
                SendMessageAfter?.Invoke(this, new NotifyEventArg(clientId, "客户端已离开"));
                //消息记录，消息记数。。。。。。
            }

        }
        catch (Exception ex)
        {
            OnSendErro?.Invoke(this, new NotifyEventArg(clientId, ex.Message));
        }
    }
    public async Task SendGroupMessage(string clientId, string msg)
    {
        try
        {
            foreach (var client in _clients)
            {
                if (client.Key!= clientId)
                {
                    if (client.Value.IsConnected)
                    {
                        byte[] bufferBack = Encoding.UTF8.GetBytes(msg);
                        await client.Value.WriteAsync(bufferBack, 0, bufferBack.Length);
                        await client.Value.FlushAsync();

                    }

                }
            }
            SendMessageAfter?.Invoke(this, new NotifyEventArg(clientId,"群发消息"+ msg));
            //消息记录，消息记数。。。。。。
        }
        catch (Exception ex)
        {
            OnSendErro?.Invoke(this, new NotifyEventArg(clientId, ex.Message));
        }
    }
}